package org.tldgen.writers;

import java.io.IOException;
import java.io.StringWriter;

import org.tldgen.model.AbstractTldElement;
import org.tldgen.model.Function;
import org.tldgen.model.Library;
import org.tldgen.model.Tag;

/**
 * Create a single HTML file
 * @author carlos
 *
 */
public abstract class AbstractHtmlWriter extends AbstractWriter {

	private static final String YUI_VERSION = "2.7.0";
	
	/** buffered contents of this writer */
	protected StringWriter out;
	
	/** filename to write */
	private String filename;
	
	protected AbstractHtmlWriter(String htmlFile) throws IOException {
		out = new StringWriter();
		this.filename = htmlFile;
	}
	
	/**
	 * Format the HTML output and writes to the output filename
	 */
	public void close() {
		formatAndWriteXml(out.toString(), filename);
	}
	
	/**
	 * @param title HTML title
	 */
	protected void startDocument(String title) throws IOException {
		print("<!DOCTYPE html>");
		startTag("html");
		startTag("head");
		startTag("title").print(title).endTag("title");
		startTag("link", "rel", "stylesheet", "type", "text/css", "href", "yui-" + YUI_VERSION + "/reset-fonts-grids.css").endTag("link");
		startTag("link", "rel", "stylesheet", "type", "text/css", "href", "styles.css").endTag("link");
		endTag("head");
	}
	
	protected void endDocument() throws IOException {
		endTag("html");
	}
	
	protected void startBody() throws IOException {
		startTag("body");
		startTag("div", "id","custom-doc","class","yui-t2");
		startTag("div", "id","bd", "role","main");
		startTag("div", "id","yui-main");
		startTag("div", "id", "wrapper", "class","yui-b left-delimiter");
	}
	
	protected void endBody(String footerName) throws IOException {
		startTag("div", "id","ft", "role","contentinfo");
		print(footerName + " TLD Documentation");
		startTag("p");
		print("Generated by ").startTag("a", "href","http://loom.extrema-sistemas.org").print("TLDGen").endTag("a");
		endTag("p");
		endTag("div");
		
		endTag("div");
		
		endTag("body");
	}

	/**
	 * 
	 * @param selectedItem If not null, the selected tag or the first function instance
	 */
	protected void printMenu(Library library, AbstractTldElement selectedItem) throws IOException {
		endTag("div");
		endTag("div");
		startTag("div", "class","yui-b menu");
		startTag("ol");
		for (Tag tag : library.getTags()) {
			printMenuItem(tag.getName() + ".html", tag.getName(), tag == selectedItem);
		}
		if (!library.getFunctions().isEmpty()) {
			printMenuItem("functions.html", "functions", selectedItem instanceof Function);
		}
		endTag("ol");
		endTag("div");
		endTag("div");
	}
	
	protected void printMenuItem(String link, String itemName, boolean selected) throws IOException {
		startTag("li", "class", selected? "selected" : null);
		startTag("a", "href", link);
		print(itemName);
		endTag("a");
		endTag("li");
	}
	
	protected void printHeader(int headerId, String value, String...attributes) throws IOException {
		startTag("h" + headerId, attributes);
		print(value);
		endTag("h" + headerId);
	}
	
	/**
	 * Write the name and the value of a table row if value not null or false
	 */
	protected void printTableEntry(String name, String value) throws IOException {
		if (isPrintable(value)) {
			printTableRow(name,value);
		}
	}
	
	/**
	 * Write all the provided values inside a table row
	 */
	protected void printTableRow(String... values) throws IOException {
		startTag("tr");
		for (String value: values) {
			startTag("td").print(value).endTag("td");
		}
		endTag("tr");
	}
	
	/**
	 * Write the table headers inside a table row
	 */
	protected void printTableHeaders(String... headers) throws IOException {
		startTag("tr");
		for (String value: headers) {
			startTag("th").print(value).endTag("th");
		}
		endTag("tr");
	}

	/**
	 * 
	 * @param tag the tag to write 
	 * @param attributes the list of pairs attribute / value, if any
	 */
	protected AbstractHtmlWriter startTag(String tag, String... attributes) throws IOException{
		print("<").print(tag);
		for (int i = 0; i < attributes.length; i += 2) {
			if (attributes[i + 1] != null) {
				print(" ").print(attributes[i]).print("=\"").print(attributes[i + 1]).print("\"");
			}
		}
		print(">");
		return this;
	}
	
	protected AbstractHtmlWriter endTag(String tag) throws IOException{
		print("</").print(tag).print(">");
		return this;
	}
	
	protected boolean isPrintable(String value) {
		return value != null;
	}
	
	protected AbstractHtmlWriter print(String s) throws IOException {
		if (isPrintable(s)) {
			out.write(s);
		}
		return this;
	}

}
